package com.firmail.aspect;

import com.firmail.controller.MockProxyController;
import com.firmail.response.ResponseInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class MockAspect {
    /**
     * TODO 时间的统计aop 过滤器
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Around("execution(* com.firmail.controller.MockProxyController.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        ResponseInfo<Object> info = new ResponseInfo<>();
        long start = System.nanoTime();
        annotation(joinPoint);
        Object proceed = joinPoint.proceed();
        info.setData(proceed);
        /*try {
            MockThreadLocal.getResponse().getWriter().println(GsonUtils.toJson(info));
        } finally {
            MockThreadLocal.clear();
        }*/

        log.info("请求处理结束：【method】 : {}, [总共耗时]： {}",
                joinPoint.getTarget() + "." + joinPoint.getSignature().getName(),
                String.format("%d ms", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)));
        return proceed;

    }

    private void anno(ProceedingJoinPoint joinPoint){

        //获取Bar实例
        //Bar bar = new Bar();
        //获取Bar的val字段
        Method method = null;
        try {
            method = MockProxyController.class.getDeclaredMethod("get", null);
            //获取val字段上的Foo注解实例
            RequestMapping foo = method.getAnnotation(RequestMapping.class);
            //获取 foo 这个代理实例所持有的 InvocationHandler
            InvocationHandler h = Proxy.getInvocationHandler(foo);
            // 获取 AnnotationInvocationHandler 的 memberValues 字段
            Field hField = null;
            try {
                hField = h.getClass().getDeclaredField("memberValues");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            // 因为这个字段事 private final 修饰，所以要打开权限
            hField.setAccessible(true);
            // 获取 memberValues
            Map memberValues = null;
            try {
                memberValues = (Map) hField.get(h);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            // 修改 value 属性值
            memberValues.put("value", "ddd");
            // 获取 foo 的 value 属性值
            String[] value = foo.value();
            System.out.println(value); // ddd
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
    private void annotation(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Annotation[] annotations = signature.getMethod().getAnnotations();
        if (annotations != null) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof RequestMapping) {
                    String[] value = ((RequestMapping) annotation).value();


                    log.debug("RequestMapping->" + Arrays.toString(value));
                    //获取 foo 这个代理实例所持有的 InvocationHandler
                    InvocationHandler h = Proxy.getInvocationHandler(annotation);
                    // 获取 AnnotationInvocationHandler 的 memberValues 字段
                    Field hField = null;
                    try {
                        hField = h.getClass().getDeclaredField("memberValues");
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }
                    // 因为这个字段事 private final 修饰，所以要打开权限
                    hField.setAccessible(true);
                    // 获取 memberValues
                    Map memberValues = null;
                    try {
                        memberValues = (Map) hField.get(h);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    // 修改 value 属性值
                    memberValues.put("value", "ddd");
                    // 获取 foo 的 value 属性值
                    //String[] valuex = ((RequestMapping) annotation).value();
                    log.info(Arrays.toString(value)); // ddd
                }

            }
        }
    }
    private void _annotation(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Annotation[] annotations = signature.getMethod().getAnnotations();
        if (annotations != null) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof RequestMapping) {
                    String[] value = ((RequestMapping) annotation).value();
                    log.debug("RequestMapping->" + Arrays.toString(value));
                    //break;
                }
            }
        }
    }
}
